﻿using System;
using System.Collections;
using System.Linq;
using System.Text;
using SimioAPI;
using SimioAPI.Extensions;
using System.Windows.Forms;

namespace WLC
{
    class WLCOrderArrivalsDefinition : IElementDefinition
    {
        #region IElementDefinition Members

        public IElement CreateElement(IElementData data)
        {
            return new WLCOrderArrivalsElement(data);
        }


        public void DefineSchema(IElementSchema schema)
        {
            IPropertyDefinitions propSchema = schema.PropertyDefinitions;
            IPropertyDefinitions repProp = propSchema.AddRepeatGroup("ArrivalList", "The repeated property group containing all scheduled arrivals for this source.");

            IPropertyDefinition productName = repProp.AddStringProperty("ProductType", String.Empty);
            productName.Description = "The name of the product contained in this order.";
            productName.Required = true;

            IPropertyDefinition quantity = repProp.AddExpressionProperty("Quantity", String.Empty);
            quantity.Description = "The quantity of this product in this order.";
            quantity.Required = true;

            IPropertyDefinition creatingSourceState = repProp.AddStateProperty("CreatingSourceState");
            creatingSourceState.Description = "The source's state variable to set in order to create a new production order.";
            creatingSourceState.Required = true;

            IPropertyDefinition creatingSourceSizeState = repProp.AddStateProperty("CreatingSourceSizeState");
            creatingSourceSizeState.Description = "The source's state variable to temporarily set the size of the next created order.";
            creatingSourceSizeState.Required = true;

            IPropertyDefinition creatingSourceDueDate = repProp.AddStateProperty("CreatingSourceDueDate");
            creatingSourceDueDate.Description = "The source's state variable to temporarily set the due date of the next created order.";
            creatingSourceDueDate.Required = true;

            IPropertyDefinition arrivalDate = repProp.AddExpressionProperty("ArrivalDate", "0");
            arrivalDate.Description = "The arrival date of the order in days from simulation start date.";
            arrivalDate.Required = true;


            IEventDefinitions events = schema.EventDefinitions;
            
            IEventDefinition createOrder = events.AddEvent("OrderCreated");
            


            

        }

        public string Name
        {
            get { return "WLCOrderArrivals"; }
        }

        public string Description
        {
            get { return "This element holds arrivals of orders which can be consumed by an WLCOrderSource."; }
        }

        public System.Drawing.Image Icon
        {
            get { return null; }
        }


        // Change GUID

        public static readonly Guid ID = new Guid("{E02F38C4-5DFA-11DF-8E4E-A3EFDED72085}");

        public Guid UniqueID
        {
            get { return ID; }
        }

        #endregion
    }


    public class WLCOrderArrivalsElement : IElement
    {
        IElementData _data;
        IRepeatingPropertyReader _wlcOrderArrivalsProp;
        IEvent _createOrderEvent;

        public WLCOrderArrivalsElement(IElementData data)
        {
            _data = data;
            _wlcOrderArrivalsProp = (IRepeatingPropertyReader)data.Properties.GetProperty("ArrivalList");
            _createOrderEvent = data.Events["OrderCreated"];
           
        }

        #region IElement Members


        public void ScheduleArrivals()
        {

            // Go through all entries in the repeated property group and schedule callback
            IPropertyReaders currentRow;
            IState currentOrderSourceState;
            IState currentOrderSourceSizeState;
            IState currentOrderDueDateState;
            double currentQuantity;


            ArrivalEntry currentArrival;
            double timeNow = _data.ExecutionContext.Calendar.TimeNow;
            double arrivalDate;

            for(int i = 0; i < _wlcOrderArrivalsProp.GetCount(_data.ExecutionContext); i++) {

                
                currentRow = _wlcOrderArrivalsProp.GetRow(i, _data.ExecutionContext);
               
                currentOrderSourceState = ((IStateProperty)currentRow.GetProperty("CreatingSourceState")).GetState(_data.ExecutionContext);
                currentOrderSourceSizeState = ((IStateProperty)currentRow.GetProperty("CreatingSourceSizeState")).GetState(_data.ExecutionContext);
                currentOrderDueDateState = ((IStateProperty)currentRow.GetProperty("CreatingSourceDueDate")).GetState(_data.ExecutionContext);
                currentQuantity = (double)currentRow.GetProperty("Quantity").GetDoubleValue(_data.ExecutionContext);
                arrivalDate = currentRow.GetProperty("ArrivalDate").GetDoubleValue(_data.ExecutionContext);

                currentArrival = new ArrivalEntry(currentOrderSourceState, currentOrderSourceSizeState, currentOrderDueDateState, currentQuantity );
                
                // Schedule event for the time when the order shall arrive
                _data.ExecutionContext.Calendar.ScheduleEvent(timeNow + (arrivalDate * 24), currentArrival, CreateArrival);
                //System.Windows.Forms.MessageBox.Show("Schedule event: " + arrivalDate + " Source:" + currentOrderSourceState.ToString());
            }

            
        }

        

        void CreateArrival(object arg) {

            ArrivalEntry thisArrival = (ArrivalEntry)arg;

            _data.ExecutionContext.ExecutionInformation.TraceInformation("ORDERARRIVALS: Creating arrival via source state " + thisArrival.OrderSourceState.Name + " with quantity " + thisArrival.Quantity);

            thisArrival.OrderSizeState.StateValue = thisArrival.Quantity;
            thisArrival.OrderDueDateState.StateValue = _data.ExecutionContext.Calendar.TimeNow + 240;
            thisArrival.OrderSourceState.StateValue = 1;

            //System.Windows.Forms.MessageBox.Show("Arrival: " + thisArrival.OrderSourceState.ToString() + " at " + _data.ExecutionContext.Calendar.TimeNow);

            // Fire event
            _createOrderEvent.Fire();
 
        }
       
        public void Initialize()
        {
            
            ScheduleArrivals();

        }

        public void Shutdown()
        {
            // No shutdown code necessary
        }



        #endregion
    }

    public class ArrivalEntry
    {
        public IState OrderSourceState { get; set; }
        public IState OrderSizeState { get; set; }
        public IState OrderDueDateState { get; set; }
        public double Quantity { get; set; }

        public ArrivalEntry(IState source, IState size, IState duedate, double quantity)
        {
            this.OrderSourceState = source;
            this.OrderSizeState = size;
            this.OrderDueDateState = duedate;
            this.Quantity = quantity;

        }


    }



}

